﻿@using Gurux.DLMS.AMI.Shared.DIs

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Gurux.DLMS.AMI.Shared.DTOs.Authentication
@using Gurux.DLMS.AMI.Shared.Rest
@using Gurux.DLMS.AMI.Shared.Enums
@using Gurux.DLMS.AMI.Client.Helpers
@using Gurux.DLMS.AMI.Module
@using Gurux.DLMS.AMI.Shared.DTOs

@attribute [Authorize(Roles = "Admin, UserManager")]
@inject NavigationManager NavigationManager
@inject HttpClient Http
@inject IGXNotifier2 Notifier
@inject AuthenticationStateProvider AuthenticationStateProvider

@if (AvailableRoles.Any() && Active != null)
{
    <EditForm Model="@Active">
        <div class="row">
            <div style="width:100%">
                <div class="form-group">
                    <label>@Properties.Resources.GivenName</label>
                    <InputText id="name" disabled="@IsDeleting" class="form-control"
                           @bind-Value="Active.GivenName" />
                </div>
                <div class="form-group">
                    <label>@Properties.Resources.Surname</label>
                    <InputText id="name" disabled="@IsDeleting" class="form-control"
                           @bind-Value="Active.Surname" />
                </div>

                <div class="form-group">
                    <label>@Properties.Resources.Email</label>
                    <InputText id="start" disabled="@IsDisabled" class="form-control"
                           @bind-Value="Active.Email" />
                </div>

                <div class="form-group">
                    <label>@Properties.Resources.Roles</label>
                    <table>
                        @for (int pos = 0; pos < AvailableRoles.Count - 1; pos += 2)
                        {
                            string role1 = AvailableRoles[pos];
                            string role2 = AvailableRoles[pos + 1];
                            <tr>
                                <th>
                                    <input type="checkbox" id="@role1"
                                           disabled="@OwnSettings(role1)" checked="@IsChecked(role1)"
                                   @onchange="@((ChangeEventArgs __e) => @Check(role1, Convert.ToBoolean(__e.Value)))" />
                                    &emsp;@role1
                                </th>
                                <th>
                                    <input type="checkbox" id="@role2"
                                           disabled="@OwnSettings(role2)" checked="@IsChecked(role2)"
                                   @onchange="@((ChangeEventArgs __e) => @Check(role2, Convert.ToBoolean(__e.Value)))" />
                                    &emsp;@role2
                                </th>
                            </tr>
                        }
                        @if (AvailableRoles.Count % 2 != 0)
                        {
                            string role = AvailableRoles[AvailableRoles.Count - 1];
                            <tr>
                                <th>
                                    <input type="checkbox" id="@role"
                                           disabled="@OwnSettings(role)" checked="@IsChecked(role)"
                                   @onchange="@((ChangeEventArgs __e) => @Check(role, Convert.ToBoolean(__e.Value)))" />
                                    &emsp;@role
                                </th>
                            </tr>
                        }
                    </table>
                </div>
            </div>
            @if (Active.CreationTime != DateTime.MinValue)
            {
                <div class="form-group">
                    <label>@Properties.Resources.CreationTime</label>
                    <InputDate Type="@InputDateType.DateTimeLocal" id="generation" readonly="readonly" class="form-control"
                       @bind-Value="Active.CreationTime" />
                </div>
            }
            @if (Active.Updated != null)
            {
                <div class="form-group">
                    <label>@Properties.Resources.Updated</label>
                    <InputDate Type="@InputDateType.DateTimeLocal" id="generation" readonly="readonly" class="form-control"
                       @bind-Value="Active.Updated" />
                </div>
            }
            @if (Active.Removed != null)
            {
                <div class="form-group">
                    <label>@Properties.Resources.Removed</label>
                    <InputDate Type="@InputDateType.DateTimeLocal" id="removed" class="form-control"
                       @bind-Value="Active.Removed" />
                </div>
            }
            @if (action == CrudAction.Delete)
            {
                <hr />
                <p>
                </p>
                <div class="form-group">
                    <InputRadioGroup @bind-Value="DeleteTarget">
                        <InputRadio Value="false">
                        </InputRadio>
                        <label>@Properties.Resources.TargetDisableQuestion</label><br>
                        <InputRadio Value="true">
                        </InputRadio>
                        <label>@Properties.Resources.TargetDeleteQuestion</label>
                    </InputRadioGroup>
                    <br />
                </div>
            }
        </div>
    </EditForm>
}

@code {
    [CascadingParameter]
    private UserTab? Parent { get; set; }

    private GXUser? _active;

    private GXUser? Active
    {
        get
        {
            if (Parent?.Active != null)
            {
                return Parent.Active;
            }
            return _active;
        }
    }

    /// <summary>
    /// User action.
    /// </summary>
    [Parameter]
    public string? Action { get; set; }

    private CrudAction action;
    /// <summary>
    /// Selected item.
    /// </summary>
    [Parameter]
    public Guid? Id { get; set; }

    private bool DeleteTarget;

    private List<string> AvailableRoles = new List<string>();
    private string? _currentUser = null;

    public bool IsChecked(string value)
    {
        return Active != null && Active.Roles != null && Active.Roles.Contains(value);
    }

    public string? IsDisabled
    {
        get
        {
            if (action == CrudAction.Create)
            {
                return null;
            }
            return "disabled";
        }
    }

    public string? IsDeleting
    {
        get
        {
            if (Notifier.Action != CrudAction.Delete)
            {
                return null;
            }
            return "disabled";
        }
    }

    /// <summary>
    /// If user modifying own settings.
    /// </summary>
    public string? OwnSettings(string value)
    {
        if (Active != null && Active.Id == _currentUser)
        {
            return "disabled";
        }
        if (Active != null && Active.Roles != null && Active.Roles.Contains(GXRoles.Admin) && value != GXRoles.Admin)
        {
            return "disabled";
        }
        return null;
    }

    public void Check(string role, bool check)
    {
        if (Active != null && Active.Roles != null)
        {
            if (check)
            {
                Active.Roles.Add(role);
            }
            else
            {
                Active.Roles.Remove(role);
            }
        }
    }

    /// <summary>
    /// Is user removed.
    /// </summary>
    private bool IsUserRemoved
    {
        get
        {
            return Active?.Removed != null;
        }
        set
        {
            if (Active != null)
            {
                Active.Removed = DateTime.Now;
            }
        }
    }

    protected override async Task OnInitializedAsync()
    {
        try
        {
            Notifier.ProgressStart();
            Notifier.ClearStatus();
            Notifier.Clear();
            if (Active == null && Id != null)
            {
                //Get user data.
                var tmp = (await Http.GetAsJsonAsync<GetUserResponse>(string.Format("api/User/{0}", Id)));
                if (tmp?.Item != null)
                {
                    _active = tmp.Item;
                }
                else
                {
                    NavigationManager.NavigateTo("404");
                }
            }
            if (Active == null)
            {
                throw new ArgumentException(Properties.Resources.InvalidTarget);
            }
            action = ClientHelpers.GetAction(Action);
            var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
            _currentUser = authState.User.FindFirst(c => c.Type == "sub")?.Value;
            ListRoles req = new ListRoles();
            var ret = await Http.PostAsJson<ListRolesResponse>("api/Role/List", req);
            if (ret != null && ret.Roles != null)
            {
                foreach (GXRole role in ret.Roles)
                {
                    AvailableRoles.Add(role.Name);
                    if (action == CrudAction.Create)
                    {
                        //Add default roles when new user is created.
                        if (role.Default.GetValueOrDefault())
                        {
                            Active.Roles.Add(role.Name);
                        }
                    }
                }
            }
            Notifier.Clear();
            if (action == CrudAction.Delete)
            {
                Notifier.AddMenuItem(new GXMenuItem() { Text = Properties.Resources.Remove, Icon = "oi oi-trash", OnClick = OnSave });

            }
            else
            {
                Notifier.AddMenuItem(new GXMenuItem() { Text = Properties.Resources.Save, Icon = "oi oi-pencil", OnClick = OnSave });
            }
            Notifier.AddMenuItem(new GXMenuItem() { Text = Properties.Resources.Cancel, Icon = "oi oi-action-undo", OnClick = OnCancel });
            Notifier.UpdateButtons();
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
        finally
        {
            Notifier?.ProgressEnd();
        }
    }

    /// <summary>
    /// Save user.
    /// </summary>
    public async void OnSave()
    {
        try
        {
            if (Active == null)
            {
                throw new Exception(Properties.Resources.InvalidTarget);
            }
            Notifier.ProgressStart();
            Notifier.ClearStatus();
            if (Notifier.Action != CrudAction.Delete && Active.Roles == null)
            {
                throw new Exception("Select user role.");
            }
            if (action == CrudAction.Delete)
            {
                await Http.PostAsJson<RemoveUserResponse>("api/User/Delete", new RemoveUser()
                    {
                        Ids = new string[] { Active.Id },
                        Delete = DeleteTarget
                    });
            }
            else
            {
                string address;
                if (action == CrudAction.Create)
                {
                    address = "api/User/Add";
                }
                else if (action == CrudAction.Update)
                {
                    address = "api/User/Update";
                }
                else
                {
                    throw new Exception(Properties.Resources.InvalidTarget);
                }
                await Http.PostAsJson<AddUserResponse>(address, new AddUser() { Users = new GXUser[] { Active } });
            }
            ClientHelpers.NavigateToLastPage(NavigationManager, Notifier);
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
        catch (Exception ex)
        {
            Notifier?.ProcessError(ex);
        }
        finally
        {
            Notifier?.ProgressEnd();
        }
    }

    /// <summary>
    /// Cancel update.
    /// </summary>
    private void OnCancel()
    {
        ClientHelpers.NavigateToLastPage(NavigationManager, Notifier);
    }
}
